/**************************************************************************************
*
*	Copyright (C) 2010 Brent Andrew O. Chua - See LICENSE.txt for more info.
*		
*	Filename	-	Shader.h
*
*	Description -	Shader class. This is a DX9 implementation for now.
*
*	Comments	-	
*					
*	Modification History:
*			Name			   Date					Description
*			CodeSushi	-	11/08/2010		-	Creation of this file
**************************************************************************************/

#ifndef _PSX_SHADER_H_
#define _PSX_SHADER_H_

#include "PulseSTD.h"
#include "ResourcePoolItem.h"
#include "Array.h"
#include "String.h"
#include "Matrix4x4.h"
#include "ShaderConstant.h"
#include "HashTable.h"
#include "GraphicsTypes.h"

#include <D3DX9Shader.h>

namespace Pulse
{

	struct ShaderDescription
	{
		EShaderType::Type type;	// Type of shader
		BOOL bDebugInfo;		// Should debug info be included in the compiled version
		String filename;		// Name of the file containing shader code
		String name;			// Identifier of the shader
		String profile;			// Shader profile would be compiled against 
		String function;		// Entry point for the shader code

		ShaderDescription( void )
			: type( EShaderType::UNKNOWN ), bDebugInfo( false )
		{
		}
	};

	class Shader : public IResourcePoolItem
	{
	public:

		Shader( void );
		//Shader( ShaderDescription *pDesc );

		virtual ~Shader( void );

		virtual BOOL CreateResource( void );
		virtual BOOL DestroyResource( void );
		virtual BOOL DisableResource( void );
		virtual BOOL RestoreResource( void );

		virtual EErrorCode::Type Create( ShaderDescription *pDesc );

		void Update( void );

		virtual void Bind( void ) const;

		virtual void Unbind( void ) const;

		virtual void SetDefaults( void ) const;

		virtual void SetFloat( const CHAR *pName, const FLOAT *pVal );
		virtual void SetFloatArray( const CHAR *pName, const float *pArray, const SIZE_T count ) const;

		virtual void SetMatrix( const CHAR *pName, const Matrix4x4 *pMat );
		virtual void SetMatrixArray( const CHAR *pName, const Matrix4x4 *pArray, const SIZE_T count ) const;

		virtual void SetInteger(const CHAR *pName, const INT *pVal );
		virtual void SetIntegerArray( const CHAR *pName, const INT *pArray, const SIZE_T count ) const;
		
		virtual void SetBoolean( const CHAR *pName, const BOOL *pVal );
		virtual void SetBooleanArray( const CHAR *pName, const BOOL *pArray, const SIZE_T count ) const;

	protected:

		virtual EErrorCode::Type CreateVertexShader( void );
		virtual EErrorCode::Type CreateGeometryShader( void );
		virtual EErrorCode::Type CreatePixelShader( void );
		virtual EErrorCode::Type CreateEffect( void );

	private:

		D3DXMACRO * GetMacros( void );

		D3DXHANDLE GetVariableByName( const CHAR *pName ) const;

		void HandleErrors( ID3DXBuffer *pErrors );

		void LoadConstants( void );

	protected:
		
		typedef Array< ShaderConstant * > ShaderVarList;
		typedef HashTable< String, ShaderConstant * > ShaderVarMapping;
		typedef Array< String > DefineList;

		IDirect3DDevice9			*m_pDevice;
		ShaderDescription			m_shaderDesc;
		mutable  ShaderVarList		m_variables;	// Array of shader variables
		mutable  ShaderVarMapping	m_varMap;		// Name to shader var mappings
		DefineList					m_defines;
		ID3DXConstantTable			*m_pConstants;

		union
		{
			IDirect3DVertexShader9	*m_pVertexShader;	// Vertex shader
			IDirect3DPixelShader9	*m_pPixelShader;	// Pixel shader
			ID3DXEffect				*m_pEffect;			// Effect shader
		};

	};

}

#endif /* _PSX_SHADER_H_ */